Everything Else That Was Already Here
Next let’s plot the moments where spatial referencing happens. Those are frames
- 198 to 223
- 265 to 288
- 352 to 380
The max gazepointindex is around 2580. At 120 Hz, that’s 21.5 seconds which is just right, that’s the length. Let’s go ahead and convert gazepointindex to seconds.
So we just have to convert frames to gazepointindex. The video is a total of 536 frames, at 25 FPS that’s 21.5 seconds. 535/25 = 21.5, so we divide all those frames by 25.
- 7.92s to 8.92s
- 10.6s to 11.52s
- 14.08s to 15.2s
And plot those!
data <- data %>%
rowwise() %>%
mutate(secs = gaze_point_index/120)
data %>%
ggplot(aes(x = secs, y = y, color = maingroup, group = name)) +
scale_y_reverse() +
geom_line() +
annotate("rect", xmin = 7.92, xmax = 8.92, ymin = 0, ymax = 900,
alpha = .2, fill = "red") +
annotate("rect", xmin = 10.6, xmax = 11.52, ymin = 0, ymax = 900,
alpha = .2, fill = "red") +
annotate("rect", xmin = 14.08, xmax = 15.2, ymin = 0, ymax = 900,
alpha = .2, fill = "red") +
theme_bw()

Maybe easier if we separate groups of signers.
data %>%
ggplot(aes(x = secs, y = y, color = maingroup, group = name)) +
scale_y_reverse() +
geom_line(alpha = 0.5) +
annotate("rect", xmin = 7.92, xmax = 8.92, ymin = 0, ymax = 900,
alpha = .2, fill = "red") +
annotate("rect", xmin = 10.6, xmax = 11.52, ymin = 0, ymax = 900,
alpha = .2, fill = "red") +
annotate("rect", xmin = 14.08, xmax = 15.2, ymin = 0, ymax = 900,
alpha = .2, fill = "red") +
facet_grid(maingroup ~ .) +
theme_bw() +
guides(color = FALSE)

Next, we’re going to add AOI position information. We’re going to pull in information on signers’ right hand position (and then apply the same idea to other body parts). I successfully wrote a function called get_xy_timestamp to do this! Yay. I’m chuffed, as the British would say.
Let’s try this on Stephanie’s data. Let’s see if we can find a correlation between any of those and the eye gaze y-position.
# We add one more row to the xy_timestamp data to align it with the end of the eye gaze data.
rhand <- get_xy_timestamp("aoi_position/Cindy_bears_FW_Position of Right Hand.txt") %>%
add_row(sec = 21.5, x = 640.16, y = 1055.97)
lhand <- get_xy_timestamp("aoi_position/Cindy_bears_FW_Position of Left Hand.txt") %>%
add_row(sec = 21.5, x = 703.74, y = 1058.39)
mouth <- get_xy_timestamp("aoi_position/Cindy_bears_FW_Position of mouth small.txt") %>%
add_row(sec = 21.5, x = 656.37, y = 373.99)
# Get Stephanie's data
steph <- filter(data, name == "Stephanie")
steph %>%
ggplot(aes(x = secs, y = y)) +
scale_y_reverse(limits = c(1200,0), expand = c(0,0)) +
geom_line(alpha = 1, color = "purple") +
# annotate("rect", xmin = 7.92, xmax = 8.92, ymin = 0, ymax = 1200,
# alpha = .2, fill = "red") +
# annotate("rect", xmin = 10.6, xmax = 11.52, ymin = 0, ymax = 1200,
# alpha = .2, fill = "red") +
# annotate("rect", xmin = 14.08, xmax = 15.2, ymin = 0, ymax = 1200,
# alpha = .2, fill = "red") +
# geom_step(data = rhand, aes(x = sec, y = y), color = "red", linetype = "longdash", alpha = 0.5) +
# geom_step(data = lhand, aes(x = sec, y = y), color = "blue", linetype = "longdash", alpha = 0.5) +
# geom_step(data = mouth, aes(x = sec, y = y), color = "black", linetype = "longdash", alpha = 0.5) +
# annotate("text", label = "Right Hand", x = 3, y = 1000, color = "red", alpha = 0.5) +
# annotate("text", label = "Left Hand", x = 3, y = 1100, color = "blue", alpha = 0.5) +
# annotate("text", label = "Mouth", x = 3, y = 200, color = "black", alpha = 0.5) +
ggtitle("Stephanie") +
theme_bw() +
theme(panel.grid.minor.y = element_blank())

steph %>%
ggplot(aes(x = secs, y = y)) +
scale_y_reverse(limits = c(1200,0), expand = c(0,0)) +
geom_line(alpha = 1, color = "purple") +
# annotate("rect", xmin = 7.92, xmax = 8.92, ymin = 0, ymax = 1200,
# alpha = .2, fill = "red") +
# annotate("rect", xmin = 10.6, xmax = 11.52, ymin = 0, ymax = 1200,
# alpha = .2, fill = "red") +
# annotate("rect", xmin = 14.08, xmax = 15.2, ymin = 0, ymax = 1200,
# alpha = .2, fill = "red") +
# geom_step(data = rhand, aes(x = sec, y = y), color = "red", linetype = "longdash", alpha = 0.5) +
# geom_step(data = lhand, aes(x = sec, y = y), color = "blue", linetype = "longdash", alpha = 0.5) +
geom_step(data = mouth, aes(x = sec, y = y), color = "black", linetype = "longdash", alpha = 0.5) +
# annotate("text", label = "Right Hand", x = 3, y = 1000, color = "red", alpha = 0.5) +
# annotate("text", label = "Left Hand", x = 3, y = 1100, color = "blue", alpha = 0.5) +
annotate("text", label = "Mouth", x = 3, y = 250, color = "black", alpha = 0.5) +
ggtitle("Stephanie") +
theme_bw() +
theme(panel.grid.minor.y = element_blank())

steph %>%
ggplot(aes(x = secs, y = y)) +
scale_y_reverse(limits = c(1200,0), expand = c(0,0)) +
geom_line(alpha = 1, color = "purple") +
# annotate("rect", xmin = 7.92, xmax = 8.92, ymin = 0, ymax = 1200,
# alpha = .2, fill = "red") +
# annotate("rect", xmin = 10.6, xmax = 11.52, ymin = 0, ymax = 1200,
# alpha = .2, fill = "red") +
# annotate("rect", xmin = 14.08, xmax = 15.2, ymin = 0, ymax = 1200,
# alpha = .2, fill = "red") +
geom_step(data = rhand, aes(x = sec, y = y), color = "red", linetype = "longdash", alpha = 0.5) +
# geom_step(data = lhand, aes(x = sec, y = y), color = "blue", linetype = "longdash", alpha = 0.5) +
geom_step(data = mouth, aes(x = sec, y = y), color = "black", linetype = "longdash", alpha = 0.5) +
annotate("text", label = "Right Hand", x = 3, y = 1000, color = "red", alpha = 0.5) +
# annotate("text", label = "Left Hand", x = 3, y = 1100, color = "blue", alpha = 0.5) +
annotate("text", label = "Mouth", x = 3, y = 250, color = "black", alpha = 0.5) +
ggtitle("Stephanie") +
theme_bw() +
theme(panel.grid.minor.y = element_blank())

steph %>%
ggplot(aes(x = secs, y = y)) +
scale_y_reverse(limits = c(1200,0), expand = c(0,0)) +
geom_line(alpha = 1, color = "purple") +
# annotate("rect", xmin = 7.92, xmax = 8.92, ymin = 0, ymax = 1200,
# alpha = .2, fill = "red") +
# annotate("rect", xmin = 10.6, xmax = 11.52, ymin = 0, ymax = 1200,
# alpha = .2, fill = "red") +
# annotate("rect", xmin = 14.08, xmax = 15.2, ymin = 0, ymax = 1200,
# alpha = .2, fill = "red") +
geom_step(data = rhand, aes(x = sec, y = y), color = "red", linetype = "longdash", alpha = 0.5) +
geom_step(data = lhand, aes(x = sec, y = y), color = "blue", linetype = "longdash", alpha = 0.5) +
geom_step(data = mouth, aes(x = sec, y = y), color = "black", linetype = "longdash", alpha = 0.5) +
annotate("text", label = "Right Hand", x = 3, y = 1000, color = "red", alpha = 0.5) +
annotate("text", label = "Left Hand", x = 3, y = 1100, color = "blue", alpha = 0.5) +
annotate("text", label = "Mouth", x = 3, y = 250, color = "black", alpha = 0.5) +
ggtitle("Stephanie") +
theme_bw() +
theme(panel.grid.minor.y = element_blank())

Now let’s work on correlations. First, our AOI vectors are not the same size as our eye gaze vectors, and the x/y position is irregularly spaced across time (irregularly spaced key frames).
# The following code will "expand" the rhand data vectors to fit the length of Stephanie's data vectors.
time_index <- steph$secs
closest <- function(x){
which.min(abs(time_index-x))
}
index_loc <- map_int(rhand$sec, closest)
rhand <- cbind(rhand, time_index[index_loc]) %>%
select(-sec) %>%
rename(sec = "time_index[index_loc]") %>%
select(sec, x, y)
rhand_full <- select(steph, secs) %>%
rename(sec = secs) %>%
left_join(rhand) %>%
fill(x) %>%
fill(y) %>%
slice(1:(nrow(.)-1))
Joining, by = "sec"
rhand_full <- rhand_full %>%
filter(sec < rhand$sec[172]) %>%
filter(sec >= rhand$sec[2])
steph <- steph %>%
filter(secs < rhand$sec[172]) %>%
filter(secs >= rhand$sec[2])
a <- rhand_full$y
a <- a[1:length(a)-1] # Shorten it by one element
b <- steph$y
# Then run correlations
cor(a,b, use = "complete.obs") # basic correlation
[1] 0.2894728
that <- ccf(a,b, lag.max = 400, type = "correlation", na.action = na.pass, plot = T) # auto-correlation

Let’s separate out individual signers.
make_signer_plots <- function(groupname, line_color) {
data %>%
filter(maingroup == groupname) %>%
ggplot(aes(x = secs, y = y)) +
scale_y_reverse() +
geom_line(alpha = 1, color = line_color) +
annotate("rect", xmin = 7.92, xmax = 8.92, ymin = 0, ymax = 900,
alpha = .2, fill = "red") +
annotate("rect", xmin = 10.6, xmax = 11.52, ymin = 0, ymax = 900,
alpha = .2, fill = "red") +
annotate("rect", xmin = 14.08, xmax = 15.2, ymin = 0, ymax = 900,
alpha = .2, fill = "red") +
geom_step(data = rhand, aes(x = sec, y = y), color = "red", linetype = "longdash", alpha = 0.5) +
geom_step(data = lhand, aes(x = sec, y = y), color = "blue", linetype = "longdash", alpha = 0.5) +
geom_step(data = mouth, aes(x = sec, y = y), color = "black", linetype = "longdash", alpha = 0.5) +
annotate("text", label = "Right Hand", x = 3, y = 1000, color = "red", alpha = 0.5) +
annotate("text", label = "Left Hand", x = 3, y = 1100, color = "blue", alpha = 0.5) +
annotate("text", label = "Mouth", x = 3, y = 200, color = "black", alpha = 0.5) +
facet_grid(name ~ .) +
ggtitle(groupname) +
theme_bw()
}
make_signer_plots("DeafEarly", "red")

make_signer_plots("DeafLate", "dark green")

make_signer_plots("HearingLate", "blue")

make_signer_plots("HearingNovice", "purple")

Okay so with Early ASL obviously very steady gaze. NoviceASL has lot of downshifts. Some align with spatial referencing, some do not. We need more of them (let’s look at other stories w better data).
Midas Forward
# Get Midas data
data <- read_csv("../Adult Data/rawdata/midasfw.csv") %>%
clean_names() %>%
rename(y = gaze_point_y_mc_spx,
language = language_value,
name = participant_name,
group = group_value)
# Pull clean names and join to data
cleannames <- read_csv("partnames.csv") %>%
distinct() %>%
rename(name = participant)
data <- data %>% left_join(cleannames, by = "name") %>%
select(-name) %>%
rename(name = new_participant) %>%
filter(!is.na(name))
# Pull final group assignments and join to data
cleangroups <- read_csv("finaldataset.csv") %>%
select(participant, maingroup) %>%
rename(name = participant) %>%
distinct()
data <- data %>% left_join(cleangroups, by = "name") %>%
select(-group)
# Let's find out who was NOT included in Three Bears
excluded <- read_csv("finaldataset.csv") %>%
select(participant, maingroup, story, direction, eye_exclude) %>%
filter(story == "KingMidas" & direction == "forward") %>%
rename(name = participant) %>%
select(name, eye_exclude)
data <- data %>% left_join(excluded, by = "name") %>%
filter(!eye_exclude) %>%
filter(!is.na(eye_exclude))
data %>% select(name, maingroup) %>% distinct()
Now let’s graph!!
Hm. One person seems wrong.
data %>%
ggplot(aes(x = gaze_point_index, y = y, color = maingroup, group = name)) + geom_line() + scale_y_reverse()

Okay it’s Jesse’s data that seems off. We’ll remove him for now and come back to it, figure out why.
data %>% filter(gaze_point_index > 30000) %>% select(name) %>% distinct() %>% head()
data <- data %>%
filter(name != "Jesse")
data %>%
ggplot(aes(x = gaze_point_index, y = y, color = maingroup, group = name)) + geom_line() +
scale_y_reverse() +
scale_x_continuous(limits = c(0,4500))

Next let’s plot the moments where spatial referencing happens. Those are frames
- 248 to 427
- 460 to 508
- 512 to 560
Like before, we’ll convert gazepointindex to seconds (by dividing 120) and all frames to seconds (by dividing 25).
- 9.92s to 17.08s
- 18.4s to 20.32s
- 20.48s to 22.4s
data <- data %>%
rowwise() %>%
mutate(secs = gaze_point_index/120)
data %>%
ggplot(aes(x = secs, y = y, color = maingroup, group = name)) +
scale_y_reverse() +
scale_x_continuous(limits = c(0, 37.5)) +
geom_line() +
annotate("rect", xmin = 9.92, xmax = 17.08, ymin = 0, ymax = 900,
alpha = .2, fill = "red") +
annotate("rect", xmin = 18.4, xmax = 20.32, ymin = 0, ymax = 900,
alpha = .2, fill = "red") +
annotate("rect", xmin = 20.48, xmax = 22.4, ymin = 0, ymax = 900,
alpha = .2, fill = "red")

Maybe easier if we separate groups of signers.
data %>%
ggplot(aes(x = secs, y = y, color = maingroup, group = name)) +
scale_y_reverse() +
scale_x_continuous(limits = c(0, 37.5)) +
geom_line(alpha = 0.5) +
annotate("rect", xmin = 9.92, xmax = 17.08, ymin = 0, ymax = 900,
alpha = .2, fill = "red") +
annotate("rect", xmin = 18.4, xmax = 20.32, ymin = 0, ymax = 900,
alpha = .2, fill = "red") +
annotate("rect", xmin = 20.48, xmax = 22.4, ymin = 0, ymax = 900,
alpha = .2, fill = "red") +
facet_grid(maingroup ~ .)

Individual signers.
data %>%
filter(maingroup == "DeafEarly") %>%
ggplot(aes(x = secs, y = y, group = name)) +
scale_x_continuous(limits = c(0, 37.5)) +
scale_y_reverse() +
geom_line(alpha = 1, color = "red") +
annotate("rect", xmin = 9.92, xmax = 17.08, ymin = 0, ymax = 900,
alpha = .2, fill = "red") +
annotate("rect", xmin = 18.4, xmax = 20.32, ymin = 0, ymax = 900,
alpha = .2, fill = "red") +
annotate("rect", xmin = 20.48, xmax = 22.4, ymin = 0, ymax = 900,
alpha = .2, fill = "red") +
facet_grid(name ~ .) +
ggtitle("DeafEarly")

data %>%
filter(maingroup == "DeafLate") %>%
ggplot(aes(x = secs, y = y, group = name)) +
scale_y_reverse() +
scale_x_continuous(limits = c(0, 37.5)) +
geom_line(alpha = 1, color = "dark green") +
annotate("rect", xmin = 9.92, xmax = 17.08, ymin = 0, ymax = 900,
alpha = .2, fill = "red") +
annotate("rect", xmin = 18.4, xmax = 20.32, ymin = 0, ymax = 900,
alpha = .2, fill = "red") +
annotate("rect", xmin = 20.48, xmax = 22.4, ymin = 0, ymax = 900,
alpha = .2, fill = "red") +
facet_grid(name ~ .) +
ggtitle("DeafLate")

data %>%
filter(maingroup == "HearingLate") %>%
ggplot(aes(x = secs, y = y, group = name)) +
scale_y_reverse() +
scale_x_continuous(limits = c(0, 37.5)) +
geom_line(alpha = 1, color = "blue") +
annotate("rect", xmin = 9.92, xmax = 17.08, ymin = 0, ymax = 900,
alpha = .2, fill = "red") +
annotate("rect", xmin = 18.4, xmax = 20.32, ymin = 0, ymax = 900,
alpha = .2, fill = "red") +
annotate("rect", xmin = 20.48, xmax = 22.4, ymin = 0, ymax = 900,
alpha = .2, fill = "red") +
facet_grid(name ~ .) +
ggtitle("HearingLate")

data %>%
filter(maingroup == "HearingNovice") %>%
ggplot(aes(x = secs, y = y, group = name)) +
scale_y_reverse() +
scale_x_continuous(limits = c(0, 37.5)) +
geom_line(alpha = 1, color = "purple") +
annotate("rect", xmin = 9.92, xmax = 17.08, ymin = 0, ymax = 900,
alpha = .2, fill = "red") +
annotate("rect", xmin = 18.4, xmax = 20.32, ymin = 0, ymax = 900,
alpha = .2, fill = "red") +
annotate("rect", xmin = 20.48, xmax = 22.4, ymin = 0, ymax = 900,
alpha = .2, fill = "red") +
facet_grid(name ~ .) +
ggtitle("HearingNovice")

LS0tCnRpdGxlOiAiU3BhdGlhbCBSZWZlcmVuY2luZyIKYXV0aG9yOiAiQWRhbSBTdG9uZSwgUGhEIgpkYXRlOiAnYHIgZm9ybWF0KFN5cy5EYXRlKCksICIlbS0lZC0lWSIpYCcKb3V0cHV0OgogIGh0bWxfbm90ZWJvb2s6CiAgICBjb2RlX2ZvbGRpbmc6IGhpZGUKICAgIGhpZ2hsaWdodDogdGFuZ28KICAgIHRoZW1lOiBwYXBlcgogICAgdG9jOiB5ZXMKICAgIHRvY19kZXB0aDogMgogICAgdG9jX2Zsb2F0OiB5ZXMKLS0tCgpgYGB7cn0KIyMgUmVhZHMgaW4gQU9JIHBvc2l0aW9uIHRleHQgZmlsZXMgZnJvbSBUb2lpCiMjIFdpbGwgcmV0dXJuIHRpYmJsZSBvZiBjb2x1bW5zIHNlYywgeCwgeSwgd2l0aCByb3dzIGZvciBlYWNoIHRpbWVzdGFtcC9BT0kgcG9zaXRpb24KCmdldF94eV90aW1lc3RhbXAgPC0gZnVuY3Rpb24oeil7Cgp4IDwtIHJlYWRfbGluZXMoeikgJT4lCiAgYXNfdGliYmxlKCkgJT4lCiAgcm93aWRfdG9fY29sdW1uKCJJRCIpCgojIHB1bGwgb3V0IHRpbWVzdGFtcCByb3dzCnRpbWVzdGFtcHMgPC0geCAlPiUKICBmaWx0ZXIoc3RyX2RldGVjdCh2YWx1ZSwgInRpbWVzdGFtcCIpKSAlPiUKICBzZXBhcmF0ZSh2YWx1ZSwgaW50byA9IGMoInRocm93IiwidGltZXN0YW1wIiksIHNlcCA9ICIgPSAiKSAlPiUKICBzZXBhcmF0ZSh0aW1lc3RhbXAsIGludG8gPSBjKCJvbmUiLCJ0d28iLCJzZWMiKSwgc2VwID0gIjoiKSAlPiUKICBzZWxlY3Qoc2VjKSAlPiUKICBtdXRhdGUoc2VjID0gYXMubnVtZXJpYyhzZWMpKQoKIyBGaW5kIEFPSSBjb29yZGluYXRlIHJvd3MKeHlzIDwtIHggJT4lCiAgbXV0YXRlKGZpbmQgPSBzdHJfZGV0ZWN0KHZhbHVlLCAiWFx0WSIpKQoKIyBmaXJzdCB2ZXJ0ZXggKDIgcm93cyBhZnRlciBlYWNoICJYWSIgbGluZSkKeHlzX3JvdyA8LSB3aGljaCh4eXMkZmluZCkgKyAyCgp4eTEgPC0geCAlPiUKICBmaWx0ZXIoSUQgJWluJSB4eXNfcm93KSAlPiUKICBzZXBhcmF0ZSh2YWx1ZSwgaW50byA9IGMoIngxIiwieTEiKSwgc2VwID0gIlx0IikgJT4lCiAgc2VsZWN0KC1JRCkKCiMgb3Bwb3NpdGUgdmVydGV4ICgyIG1vcmUgcm93cyBkb3duKQp4eXNfcm93IDwtIHh5c19yb3cgKyAyCgp4eTIgPC0geCAlPiUKICBmaWx0ZXIoSUQgJWluJSB4eXNfcm93KSAlPiUKICBzZXBhcmF0ZSh2YWx1ZSwgaW50byA9IGMoIngyIiwieTIiKSwgc2VwID0gIlx0IikgJT4lCiAgc2VsZWN0KC1JRCkKCiMgTm93IGdldCBhdmVyYWdlIFhZIHBvc2l0aW9uIHBlciB0aW1lc3RhbXAKeHlzIDwtIGNiaW5kKHRpbWVzdGFtcHMsIHh5MSwgeHkyKSAlPiUKICBtdXRhdGVfYWxsKGFzLm51bWVyaWMpICU+JQogIHJvd3dpc2UoKSAlPiUKICBtdXRhdGUoeCA9IG1lYW4oeDEseDIpLAogICAgICAgICB5ID0gbWVhbih5MSwgeTIpKSAlPiUKICBzZWxlY3Qoc2VjLCB4LCB5KQp9CmBgYAoKTGV0J3MgZ2l2ZSB0aGlzIGEgc2hvdCEhCgojIFRocmVlIEJlYXJzIEZvcndhcmQgCkZpcnN0IGxldCdzIHNlZSB3aG8ncyBpbiBvdXIgZGF0YXNldC4gVGhpcyBpcyBUZXN0IDEgLSAzIEJlYXJzIC0gRm9yd2FyZC4gV2UncmUgcHVsbGluZyBjbGVhbmVkLXVwIG5hbWVzIGFuZCBhc3NpZ25lZCBncm91cHMgZnJvbSBvdXIgZmluYWwgZGF0YXNldCB0aGF0IHdlIHVzZWQgaW4gb3VyIEFPSSBhbmFseXNpcy4gVGhlbiB3ZSBhcmUgcmVtb3ZpbmcgcGFydGljaXBhbnRzIHdob3NlIFRocmVlIEJlYXJzIEZvcndhcmQgc3Rvcnkgd2Fzbid0IGluY2x1ZGVkIGluIG91ciBBT0kgYW5hbHlzaXMgZHVlIHRvIDwyNSUgbG9va2luZyB0aW1lIG9yIG90aGVyIHJlYXNvbnMuIAoKYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KbGlicmFyeSh0aWR5dmVyc2UpCmxpYnJhcnkob3Blbnhsc3gpCmxpYnJhcnkoamFuaXRvcikKCiMgR2V0IFRocmVlIEJlYXJzIGRhdGEKZGF0YSA8LSByZWFkLnhsc3goIlRlc3QxX0NpbmR5X2JlYXJzX0ZXX0V4YW1pbmUgZm9yIFNwYXRpYWwgUmVmZXJlbmNpbmcueGxzeCIpICU+JQogIGNsZWFuX25hbWVzKCkgJT4lCiAgcmVuYW1lKHkgPSBnYXplX3BvaW50X3lfbWNfc3B4LAogICAgICAgICBsYW5ndWFnZSA9IGxhbmd1YWdlX3ZhbHVlLAogICAgICAgICBuYW1lID0gcGFydGljaXBhbnRfbmFtZSwKICAgICAgICAgZ3JvdXAgPSBncm91cF92YWx1ZSkKCiMgUHVsbCBjbGVhbiBuYW1lcyBhbmQgam9pbiB0byBkYXRhIChhbmQgYWRkIExhdXJhMiBmb3IgTGF1cmEgKG1pc3Npbmcgc3RvcmllcykpCmNsZWFubmFtZXMgPC0gcmVhZF9jc3YoInBhcnRuYW1lcy5jc3YiKSAlPiUKICBkaXN0aW5jdCgpICU+JQogIHJlbmFtZShuYW1lID0gcGFydGljaXBhbnQpICU+JQogIGZpbHRlcihuYW1lICE9ICJMYXVyYTIiKQoKZGF0YSA8LSBkYXRhICU+JSAKICBsZWZ0X2pvaW4oY2xlYW5uYW1lcywgYnkgPSAibmFtZSIpICU+JQogIHNlbGVjdCgtbmFtZSkgJT4lCiAgcmVuYW1lKG5hbWUgPSBuZXdfcGFydGljaXBhbnQpICU+JQogIGZpbHRlcighaXMubmEobmFtZSkpCgojIFB1bGwgZmluYWwgZ3JvdXAgYXNzaWdubWVudHMgYW5kIGpvaW4gdG8gZGF0YQpjbGVhbmdyb3VwcyA8LSByZWFkX2NzdigiZmluYWxkYXRhc2V0LmNzdiIpICU+JQogIHNlbGVjdChwYXJ0aWNpcGFudCwgbWFpbmdyb3VwKSAlPiUKICByZW5hbWUobmFtZSA9IHBhcnRpY2lwYW50KSAlPiUKICBkaXN0aW5jdCgpCgpkYXRhIDwtIGRhdGEgJT4lIGxlZnRfam9pbihjbGVhbmdyb3VwcywgYnkgPSAibmFtZSIpICU+JQogIHNlbGVjdCgtZ3JvdXApCgojIExldCdzIGZpbmQgb3V0IHdobyB3YXMgTk9UIGluY2x1ZGVkIGluIFRocmVlIEJlYXJzCmV4Y2x1ZGVkIDwtIHJlYWRfY3N2KCJmaW5hbGRhdGFzZXQuY3N2IikgJT4lCiAgc2VsZWN0KHBhcnRpY2lwYW50LCBtYWluZ3JvdXAsIHN0b3J5LCBkaXJlY3Rpb24sIGV5ZV9leGNsdWRlKSAlPiUKICBmaWx0ZXIoc3RvcnkgPT0gIkdvbGRpbG9ja3MiICYgZGlyZWN0aW9uID09ICJmb3J3YXJkIikgJT4lCiAgcmVuYW1lKG5hbWUgPSBwYXJ0aWNpcGFudCkgJT4lCiAgc2VsZWN0KG5hbWUsIGV5ZV9leGNsdWRlKQoKZGF0YSA8LSBkYXRhICU+JSBsZWZ0X2pvaW4oZXhjbHVkZWQsIGJ5ID0gIm5hbWUiKSAlPiUKICBmaWx0ZXIoIWV5ZV9leGNsdWRlKSAlPiUKICBmaWx0ZXIoIWlzLm5hKGV5ZV9leGNsdWRlKSkKCmRhdGEgJT4lIHNlbGVjdChuYW1lLCBtYWluZ3JvdXApICU+JSBkaXN0aW5jdCgpCmBgYAoKTm93IGxldCdzIGdyYXBoISEgCgpNZXNzeSwgSSBrbm93LCBidXQgYWxyZWFkeSB3ZSBjYW4gc2VlIHNvbWUgSGVhcmluZ05vdmljZSBoYXMgYmlnIHNoaWZ0cyBkb3dud2FyZC4gQW5kIHNvbWUgSGVhcmluZ0xhdGUgdG9vLgoKYGBge3J9CmRhdGEgJT4lCiAgZ2dwbG90KGFlcyh4ID0gZ2F6ZV9wb2ludF9pbmRleCwgeSA9IHksIGNvbG9yID0gbWFpbmdyb3VwLCBncm91cCA9IG5hbWUpKSArIGdlb21fbGluZSgpICsgCiAgc2NhbGVfeV9yZXZlcnNlKGxpbWl0cyA9IGMoMTIwMCwwKSkgKwogIHRoZW1lX2J3KCkKYGBgCgojIEdyb3VwIEF2ZXJhZ2VzCgpOZXh0LCBsZXQncyBtYWtlIGdyb3VwIGF2ZXJhZ2VzLiAKCmBgYHtyfQphdmVyYWdlZF95IDwtIGRhdGEgJT4lCiAgZ3JvdXBfYnkobWFpbmdyb3VwLCBnYXplX3BvaW50X2luZGV4KSAlPiUKICBzdW1tYXJpc2UoeV9tZWFuID0gbWVhbih5LCBuYS5ybSA9IFQpLAogICAgICAgICAgICB5X3NkID0gc2QoeSwgbmEucm0gPSBUKSwKICAgICAgICAgICAgeV9jb3VudCA9IG4oKSwKICAgICAgICAgICAgeV9zZSA9IHlfc2Qvc3FydCh5X2NvdW50KSkKCmF2ZXJhZ2VkX3kgJT4lCiAgZ2dwbG90KCkgKyAKICBnZW9tX2xpbmUoYWVzKHggPSBnYXplX3BvaW50X2luZGV4LCB5ID0geV9tZWFuLCBjb2xvciA9IG1haW5ncm91cCkpICsKICBnZW9tX3JpYmJvbihhZXMoeCA9IGdhemVfcG9pbnRfaW5kZXgsIAogICAgICAgICAgICAgICAgICB5bWluID0geV9tZWFuLXlfc2UsIAogICAgICAgICAgICAgICAgICB5bWF4ID0geV9tZWFuK3lfc2UsCiAgICAgICAgICAgICAgICAgIGZpbGwgPSBtYWluZ3JvdXApLCBhbHBoYSA9IDAuNSkgKwogIHNjYWxlX3lfcmV2ZXJzZShsaW1pdHMgPSBjKDEyMDAsMCkpICsKICB0aGVtZV9idygpICsKICBmYWNldF93cmFwKCJtYWluZ3JvdXAiKQoKYXZlcmFnZWRfeSAlPiUKICBnZ3Bsb3QoKSArIAogIGdlb21fbGluZShhZXMoeCA9IGdhemVfcG9pbnRfaW5kZXgsIHkgPSB5X21lYW4sIGNvbG9yID0gbWFpbmdyb3VwKSkgKwogIGdlb21fcmliYm9uKGFlcyh4ID0gZ2F6ZV9wb2ludF9pbmRleCwgCiAgICAgICAgICAgICAgICAgIHltaW4gPSB5X21lYW4teV9zZSwgCiAgICAgICAgICAgICAgICAgIHltYXggPSB5X21lYW4reV9zZSwKICAgICAgICAgICAgICAgICAgZmlsbCA9IG1haW5ncm91cCksIGFscGhhID0gMC41KSArCiAgc2NhbGVfeV9yZXZlcnNlKGxpbWl0cyA9IGMoMTIwMCwwKSkgKwogIHRoZW1lX2J3KCkKYGBgCgojIEdyb3VwIEF2ZXJhZ2VzIFdpdGggU21vb3RoaW5nCgpTbyBJJ2xsIGJhY2sgdXAgYW5kIHNtb290aCBlYWNoIHBlcnNvbidzIGRhdGEgdXNpbmcgYSBtb3ZpbmcgYXZlcmFnZSB3aW5kb3cgb2Ygc3BhbiA9IDUuIFRha2VuIGZyb20gb3VyIGFkdWx0IG1hbnVzY3JpcHQgd2hpY2ggaGFkIHRoaXM6IAoKPiBUaGUgZGF0YSB3ZXJlIHRoZW4gc21vb3RoZWQgd2l0aCBhIHN0YW5kYXJkIG1vdmluZyBhdmVyYWdlIG5vaXNlIHJlZHVjdGlvbiBhbGdvcml0aG0gKHdpbmRvdyBzaXplID0gNSBzYW1wbGVzKSB3aGljaCBhY3RzIGFzIGEgbG93LXBhc3MgZmlsdGVyIHRoYXQgcmVkdWNlcyB0aGUgaW5mbHVlbmNlIG9mIG1pY3Jvc2FjY2FkZXMsIGJsaW5rcywgYW5kIGxhcmdlIGRhdGEgZ2FwcyAoYmFzZWQgb24gWWFyYnVzLCAxOTY3KS4gCgpUaGUgYmVsb3cgY2hhcnQgc2hvd3MgQWRhbSdzIGRhdGEsIGJsdWUgaXMgdW5zbW9vdGhlZCBhbmQgcmVkIGlzIHNtb290aGVkLiAKCgpgYGB7cn0KZGF0YSA8LSBkYXRhICU+JQogIGdyb3VwX2J5KG1haW5ncm91cCwgcmVjb3JkaW5nX25hbWUpICU+JQogIG11dGF0ZSh5X21hID0gUmNwcFJvbGw6OnJvbGxfbWVhbih5LCBuID0gNSwgZmlsbCA9IDApKQoKZGF0YSAlPiUKICBmaWx0ZXIocmVjb3JkaW5nX25hbWUgPT0gIkFkYW1fR29vZCIpICU+JQogIGdncGxvdCgpICsKICBnZW9tX2xpbmUoYWVzKHggPSBnYXplX3BvaW50X2luZGV4LCB5ID0geSksIGNvbG9yID0gImJsdWUiLCBhbHBoYSA9IDAuMjUsIHNpemUgPSAwLjUpICsKICBnZW9tX2xpbmUoYWVzKHggPSBnYXplX3BvaW50X2luZGV4LCB5ID0geV9tYSksIGNvbG9yID0gInJlZCIsIHNpemUgPSAwLjIpICsKICBzY2FsZV95X3JldmVyc2UobGltaXRzID0gYyg0NzUsIDMyNSkpICsKICB0aGVtZV9idygpCmBgYAoKU28gdGhhdCdzIG5pY2UuIExldCdzIGdvIGRvIGdyb3VwIGF2ZXJhZ2VzIGFnYWluLiAKCmBgYHtyfQphdmVyYWdlZF95IDwtIGRhdGEgJT4lCiAgZ3JvdXBfYnkobWFpbmdyb3VwLCBnYXplX3BvaW50X2luZGV4KSAlPiUKICBzdW1tYXJpc2UoeV9tZWFuID0gbWVhbih5X21hLCBuYS5ybSA9IFQpLAogICAgICAgICAgICB5X3NkID0gc2QoeV9tYSwgbmEucm0gPSBUKSwKICAgICAgICAgICAgeV9jb3VudCA9IG4oKSwKICAgICAgICAgICAgeV9zZSA9IHlfc2Qvc3FydCh5X2NvdW50KSkKCmF2ZXJhZ2VkX3kgJT4lCiAgZ2dwbG90KCkgKyAKICBnZW9tX2xpbmUoYWVzKHggPSBnYXplX3BvaW50X2luZGV4LCB5ID0geV9tZWFuLCBjb2xvciA9IG1haW5ncm91cCkpICsKICBnZW9tX3JpYmJvbihhZXMoeCA9IGdhemVfcG9pbnRfaW5kZXgsIAogICAgICAgICAgICAgICAgICB5bWluID0geV9tZWFuLXlfc2UsIAogICAgICAgICAgICAgICAgICB5bWF4ID0geV9tZWFuK3lfc2UsCiAgICAgICAgICAgICAgICAgIGZpbGwgPSBtYWluZ3JvdXApLCBhbHBoYSA9IDAuNSkgKwogIHNjYWxlX3lfcmV2ZXJzZShsaW1pdHMgPSBjKDEyMDAsMCkpICsKICB0aGVtZV9idygpICsKICBmYWNldF93cmFwKCJtYWluZ3JvdXAiKQoKYXZlcmFnZWRfeSAlPiUKICBnZ3Bsb3QoKSArIAogIGdlb21fbGluZShhZXMoeCA9IGdhemVfcG9pbnRfaW5kZXgsIHkgPSB5X21lYW4sIGNvbG9yID0gbWFpbmdyb3VwKSkgKwogIGdlb21fcmliYm9uKGFlcyh4ID0gZ2F6ZV9wb2ludF9pbmRleCwgCiAgICAgICAgICAgICAgICAgIHltaW4gPSB5X21lYW4teV9zZSwgCiAgICAgICAgICAgICAgICAgIHltYXggPSB5X21lYW4reV9zZSwKICAgICAgICAgICAgICAgICAgZmlsbCA9IG1haW5ncm91cCksIGFscGhhID0gMC41KSArCiAgc2NhbGVfeV9yZXZlcnNlKGxpbWl0cyA9IGMoMTIwMCwwKSkgKwogIHRoZW1lX2J3KCkKCmF2ZXJhZ2VkX3kgJT4lCiAgZmlsdGVyKG1haW5ncm91cCA9PSAiRGVhZkVhcmx5IiB8IG1haW5ncm91cCA9PSAiSGVhcmluZ05vdmljZSIpICU+JQogIGdncGxvdCgpICsgCiAgZ2VvbV9saW5lKGFlcyh4ID0gZ2F6ZV9wb2ludF9pbmRleCwgeSA9IHlfbWVhbiwgY29sb3IgPSBtYWluZ3JvdXApKSArCiAgZ2VvbV9yaWJib24oYWVzKHggPSBnYXplX3BvaW50X2luZGV4LCAKICAgICAgICAgICAgICAgICAgeW1pbiA9IHlfbWVhbi15X3NlLCAKICAgICAgICAgICAgICAgICAgeW1heCA9IHlfbWVhbit5X3NlLAogICAgICAgICAgICAgICAgICBmaWxsID0gbWFpbmdyb3VwKSwgYWxwaGEgPSAwLjUpICsKICBzY2FsZV95X3JldmVyc2UobGltaXRzID0gYyg3MDAsMzAwKSkgKwogIHRoZW1lX2J3KCkKYGBgCgojIEdyb3VwIEF2ZXJhZ2VzIFdpdGggTW9yZSBTbW9vdGhpbmcKCk1heWJlIHdlIHNob3VsZCBzbW9vdGggZXZlbiBtb3JlLiBTYW1wbGUgc2l6ZSA9IDEwISAKCmBgYHtyfQpkYXRhIDwtIGRhdGEgJT4lCiAgZ3JvdXBfYnkobWFpbmdyb3VwLCByZWNvcmRpbmdfbmFtZSkgJT4lCiAgbXV0YXRlKHlfbWEyID0gUmNwcFJvbGw6OnJvbGxfbWVhbih5LCBuID0gMTAsIGZpbGwgPSAwKSkKCiMgZGF0YSAlPiUKIyAgIGZpbHRlcihyZWNvcmRpbmdfbmFtZSA9PSAiQWRhbV9Hb29kIikgJT4lCiMgICBnZ3Bsb3QoKSArCiMgICBnZW9tX2xpbmUoYWVzKHggPSBnYXplX3BvaW50X2luZGV4LCB5ID0geSksIGNvbG9yID0gImJsdWUiLCBhbHBoYSA9IDAuMjUsIHNpemUgPSAwLjUpICsKIyAgIGdlb21fbGluZShhZXMoeCA9IGdhemVfcG9pbnRfaW5kZXgsIHkgPSB5X21hMiksIGNvbG9yID0gInJlZCIsIHNpemUgPSAwLjIpICsKIyAgIHNjYWxlX3lfcmV2ZXJzZShsaW1pdHMgPSBjKDQ3NSwgMzI1KSkgKwojICAgdGhlbWVfYncoKQoKYXZlcmFnZWRfeSA8LSBkYXRhICU+JQogIGdyb3VwX2J5KG1haW5ncm91cCwgZ2F6ZV9wb2ludF9pbmRleCkgJT4lCiAgc3VtbWFyaXNlKHlfbWVhbiA9IG1lYW4oeV9tYTIsIG5hLnJtID0gVCksCiAgICAgICAgICAgIHlfc2QgPSBzZCh5X21hMiwgbmEucm0gPSBUKSwKICAgICAgICAgICAgeV9jb3VudCA9IG4oKSwKICAgICAgICAgICAgeV9zZSA9IHlfc2Qvc3FydCh5X2NvdW50KSkKCmxpYnJhcnkoaHJicnRoZW1lcykKYXZlcmFnZWRfeSAlPiUKICBnZ3Bsb3QoKSArIAogIGdlb21fbGluZShhZXMoeCA9IGdhemVfcG9pbnRfaW5kZXgsIHkgPSB5X21lYW4sIGNvbG9yID0gbWFpbmdyb3VwKSwgc2l6ZSA9IDAuOCkgKwogIGdlb21fcmliYm9uKGFlcyh4ID0gZ2F6ZV9wb2ludF9pbmRleCwgCiAgICAgICAgICAgICAgICAgIHltaW4gPSB5X21lYW4teV9zZSwgCiAgICAgICAgICAgICAgICAgIHltYXggPSB5X21lYW4reV9zZSwKICAgICAgICAgICAgICAgICAgZmlsbCA9IG1haW5ncm91cCksIGFscGhhID0gMC41KSArCiAgc2NhbGVfeV9yZXZlcnNlKGxpbWl0cyA9IGMoMTIwMCwwKSkgKwogIGZhY2V0X3dyYXAoIm1haW5ncm91cCIpICsKICBsYWJzKHggPSAidGltZSAobXMpIiwgeSA9ICJwaXhlbHMiLCB0aXRsZSA9ICJGaWd1cmUgMS4gVmVydGljYWwgRXllIEdhemUgUG9zaXRpb24gQWNyb3NzIE9uZSBBU0wgTmFycmF0aXZlIikgKwogIGd1aWRlcyhjb2xvciA9IEYsIGZpbGwgPSBGKSArCiAgdGhlbWVfaXBzdW1fcmMoKQoKYXZlcmFnZWRfeSAlPiUKICBnZ3Bsb3QoKSArIAogIGdlb21fbGluZShhZXMoeCA9IGdhemVfcG9pbnRfaW5kZXgsIHkgPSB5X21lYW4sIGNvbG9yID0gbWFpbmdyb3VwKSkgKwogIGdlb21fcmliYm9uKGFlcyh4ID0gZ2F6ZV9wb2ludF9pbmRleCwgCiAgICAgICAgICAgICAgICAgIHltaW4gPSB5X21lYW4teV9zZSwgCiAgICAgICAgICAgICAgICAgIHltYXggPSB5X21lYW4reV9zZSwKICAgICAgICAgICAgICAgICAgZmlsbCA9IG1haW5ncm91cCksIGFscGhhID0gMC41KSArCiAgc2NhbGVfeV9yZXZlcnNlKGxpbWl0cyA9IGMoMTIwMCwwKSkgKwogIHRoZW1lX2J3KCkKCmF2ZXJhZ2VkX3kgJT4lCiAgZmlsdGVyKG1haW5ncm91cCA9PSAiRGVhZkVhcmx5IiB8IG1haW5ncm91cCA9PSAiSGVhcmluZ05vdmljZSIpICU+JQogIGdncGxvdCgpICsgCiAgZ2VvbV9saW5lKGFlcyh4ID0gZ2F6ZV9wb2ludF9pbmRleCwgeSA9IHlfbWVhbiwgY29sb3IgPSBtYWluZ3JvdXApLCBzaXplID0gMC44KSArCiAgZ2VvbV9yaWJib24oYWVzKHggPSBnYXplX3BvaW50X2luZGV4LCAKICAgICAgICAgICAgICAgICAgeW1pbiA9IHlfbWVhbi15X3NlLCAKICAgICAgICAgICAgICAgICAgeW1heCA9IHlfbWVhbit5X3NlLAogICAgICAgICAgICAgICAgICBmaWxsID0gbWFpbmdyb3VwKSwgYWxwaGEgPSAwLjEpICsKICBzY2FsZV95X3JldmVyc2UobGltaXRzID0gYyg3MDAsMzAwKSkgKwogIGxhYnMoeCA9ICJ0aW1lIChtcykiLCB5ID0gInBpeGVscyIsIHRpdGxlID0gIkZpZ3VyZSAyLiBEZWFmIEVhcmx5IFNpZ25lcnMgdnMuIEhlYXJpbmcgTm92aWNlIFNpZ25lcnMiLCBjb2xvciA9ICIiLCBmaWxsID0gIiIpICsKICB0aGVtZV9pcHN1bV9yYygpCgpgYGAKCiMgRXZlcnl0aGluZyBFbHNlIFRoYXQgV2FzIEFscmVhZHkgSGVyZQoKTmV4dCBsZXQncyBwbG90IHRoZSBtb21lbnRzIHdoZXJlIHNwYXRpYWwgcmVmZXJlbmNpbmcgaGFwcGVucy4gVGhvc2UgYXJlIGZyYW1lcwoKMS4gMTk4IHRvIDIyMwoxLiAyNjUgdG8gMjg4CjEuIDM1MiB0byAzODAKClRoZSBtYXggZ2F6ZXBvaW50aW5kZXggaXMgYXJvdW5kIDI1ODAuIEF0IDEyMCBIeiwgdGhhdCdzIDIxLjUgc2Vjb25kcyB3aGljaCBpcyBqdXN0IHJpZ2h0LCB0aGF0J3MgdGhlIGxlbmd0aC4gTGV0J3MgZ28gYWhlYWQgYW5kIGNvbnZlcnQgZ2F6ZXBvaW50aW5kZXggdG8gc2Vjb25kcy4gIAoKU28gd2UganVzdCBoYXZlIHRvIGNvbnZlcnQgZnJhbWVzIHRvIGdhemVwb2ludGluZGV4LiBUaGUgdmlkZW8gaXMgYSB0b3RhbCBvZiA1MzYgZnJhbWVzLCBhdCAyNSBGUFMgdGhhdCdzIDIxLjUgc2Vjb25kcy4gNTM1LzI1ID0gMjEuNSwgc28gd2UgZGl2aWRlIGFsbCB0aG9zZSBmcmFtZXMgYnkgMjUuIAoKMS4gNy45MnMgdG8gOC45MnMKMS4gMTAuNnMgdG8gMTEuNTJzCjEuIDE0LjA4cyB0byAxNS4ycyAKCkFuZCBwbG90IHRob3NlIQoKYGBge3J9CmRhdGEgPC0gZGF0YSAlPiUKICByb3d3aXNlKCkgJT4lCiAgbXV0YXRlKHNlY3MgPSBnYXplX3BvaW50X2luZGV4LzEyMCkKCmRhdGEgJT4lCiAgZ2dwbG90KGFlcyh4ID0gc2VjcywgeSA9IHksIGNvbG9yID0gbWFpbmdyb3VwLCBncm91cCA9IG5hbWUpKSArIAogIHNjYWxlX3lfcmV2ZXJzZSgpICsgCiAgZ2VvbV9saW5lKCkgKyAKICBhbm5vdGF0ZSgicmVjdCIsIHhtaW4gPSA3LjkyLCB4bWF4ID0gOC45MiwgeW1pbiA9IDAsIHltYXggPSA5MDAsCiAgYWxwaGEgPSAuMiwgZmlsbCA9ICJyZWQiKSArCiAgYW5ub3RhdGUoInJlY3QiLCB4bWluID0gMTAuNiwgeG1heCA9IDExLjUyLCB5bWluID0gMCwgeW1heCA9IDkwMCwKICBhbHBoYSA9IC4yLCBmaWxsID0gInJlZCIpICsKICBhbm5vdGF0ZSgicmVjdCIsIHhtaW4gPSAxNC4wOCwgeG1heCA9IDE1LjIsIHltaW4gPSAwLCB5bWF4ID0gOTAwLAogIGFscGhhID0gLjIsIGZpbGwgPSAicmVkIikgKwogIHRoZW1lX2J3KCkKYGBgCgpNYXliZSBlYXNpZXIgaWYgd2Ugc2VwYXJhdGUgZ3JvdXBzIG9mIHNpZ25lcnMuIAoKYGBge3J9CmRhdGEgJT4lCiAgZ2dwbG90KGFlcyh4ID0gc2VjcywgeSA9IHksIGNvbG9yID0gbWFpbmdyb3VwLCBncm91cCA9IG5hbWUpKSArIAogIHNjYWxlX3lfcmV2ZXJzZSgpICsgCiAgZ2VvbV9saW5lKGFscGhhID0gMC41KSArIAogIGFubm90YXRlKCJyZWN0IiwgeG1pbiA9IDcuOTIsIHhtYXggPSA4LjkyLCB5bWluID0gMCwgeW1heCA9IDkwMCwKICBhbHBoYSA9IC4yLCBmaWxsID0gInJlZCIpICsKICBhbm5vdGF0ZSgicmVjdCIsIHhtaW4gPSAxMC42LCB4bWF4ID0gMTEuNTIsIHltaW4gPSAwLCB5bWF4ID0gOTAwLAogIGFscGhhID0gLjIsIGZpbGwgPSAicmVkIikgKwogIGFubm90YXRlKCJyZWN0IiwgeG1pbiA9IDE0LjA4LCB4bWF4ID0gMTUuMiwgeW1pbiA9IDAsIHltYXggPSA5MDAsCiAgYWxwaGEgPSAuMiwgZmlsbCA9ICJyZWQiKSArCiAgZmFjZXRfZ3JpZChtYWluZ3JvdXAgfiAuKSArCiAgdGhlbWVfYncoKSArCiAgZ3VpZGVzKGNvbG9yID0gRkFMU0UpCmBgYAoKTmV4dCwgd2UncmUgZ29pbmcgdG8gYWRkIEFPSSBwb3NpdGlvbiBpbmZvcm1hdGlvbi4gV2UncmUgZ29pbmcgdG8gcHVsbCBpbiBpbmZvcm1hdGlvbiBvbiBzaWduZXJzJyByaWdodCBoYW5kIHBvc2l0aW9uIChhbmQgdGhlbiBhcHBseSB0aGUgc2FtZSBpZGVhIHRvIG90aGVyIGJvZHkgcGFydHMpLiBJIHN1Y2Nlc3NmdWxseSB3cm90ZSBhIGZ1bmN0aW9uIGNhbGxlZCBgZ2V0X3h5X3RpbWVzdGFtcGAgdG8gZG8gdGhpcyEgWWF5LiBJJ20gY2h1ZmZlZCwgYXMgdGhlIEJyaXRpc2ggd291bGQgc2F5LgoKTGV0J3MgdHJ5IHRoaXMgb24gU3RlcGhhbmllJ3MgZGF0YS4gTGV0J3Mgc2VlIGlmIHdlIGNhbiBmaW5kIGEgY29ycmVsYXRpb24gYmV0d2VlbiBhbnkgb2YgdGhvc2UgYW5kIHRoZSBleWUgZ2F6ZSB5LXBvc2l0aW9uLiAKCmBgYHtyfQoKIyBXZSBhZGQgb25lIG1vcmUgcm93IHRvIHRoZSB4eV90aW1lc3RhbXAgZGF0YSB0byBhbGlnbiBpdCB3aXRoIHRoZSBlbmQgb2YgdGhlIGV5ZSBnYXplIGRhdGEuCnJoYW5kIDwtIGdldF94eV90aW1lc3RhbXAoImFvaV9wb3NpdGlvbi9DaW5keV9iZWFyc19GV19Qb3NpdGlvbiBvZiBSaWdodCBIYW5kLnR4dCIpICU+JQogIGFkZF9yb3coc2VjID0gMjEuNSwgeCA9IDY0MC4xNiwgeSA9IDEwNTUuOTcpCmxoYW5kIDwtIGdldF94eV90aW1lc3RhbXAoImFvaV9wb3NpdGlvbi9DaW5keV9iZWFyc19GV19Qb3NpdGlvbiBvZiBMZWZ0IEhhbmQudHh0IikgJT4lCiAgYWRkX3JvdyhzZWMgPSAyMS41LCB4ID0gNzAzLjc0LCB5ID0gMTA1OC4zOSkKbW91dGggPC0gZ2V0X3h5X3RpbWVzdGFtcCgiYW9pX3Bvc2l0aW9uL0NpbmR5X2JlYXJzX0ZXX1Bvc2l0aW9uIG9mIG1vdXRoIHNtYWxsLnR4dCIpICU+JQogIGFkZF9yb3coc2VjID0gMjEuNSwgeCA9IDY1Ni4zNywgeSA9IDM3My45OSkKCiMgR2V0IFN0ZXBoYW5pZSdzIGRhdGEKc3RlcGggPC0gZmlsdGVyKGRhdGEsIG5hbWUgPT0gIlN0ZXBoYW5pZSIpCgpzdGVwaCAlPiUKICBnZ3Bsb3QoYWVzKHggPSBzZWNzLCB5ID0geSkpICsgCiAgc2NhbGVfeV9yZXZlcnNlKGxpbWl0cyA9IGMoMTIwMCwwKSwgZXhwYW5kID0gYygwLDApKSArIAogIGdlb21fbGluZShhbHBoYSA9IDEsIGNvbG9yID0gInB1cnBsZSIpICsgCiAgIyBhbm5vdGF0ZSgicmVjdCIsIHhtaW4gPSA3LjkyLCB4bWF4ID0gOC45MiwgeW1pbiA9IDAsIHltYXggPSAxMjAwLAogICMgYWxwaGEgPSAuMiwgZmlsbCA9ICJyZWQiKSArCiAgIyBhbm5vdGF0ZSgicmVjdCIsIHhtaW4gPSAxMC42LCB4bWF4ID0gMTEuNTIsIHltaW4gPSAwLCB5bWF4ID0gMTIwMCwKICAjIGFscGhhID0gLjIsIGZpbGwgPSAicmVkIikgKwogICMgYW5ub3RhdGUoInJlY3QiLCB4bWluID0gMTQuMDgsIHhtYXggPSAxNS4yLCB5bWluID0gMCwgeW1heCA9IDEyMDAsCiAgIyBhbHBoYSA9IC4yLCBmaWxsID0gInJlZCIpICsKICAjIGdlb21fc3RlcChkYXRhID0gcmhhbmQsIGFlcyh4ID0gc2VjLCB5ID0geSksIGNvbG9yID0gInJlZCIsIGxpbmV0eXBlID0gImxvbmdkYXNoIiwgYWxwaGEgPSAwLjUpICsgCiAgIyBnZW9tX3N0ZXAoZGF0YSA9IGxoYW5kLCBhZXMoeCA9IHNlYywgeSA9IHkpLCBjb2xvciA9ICJibHVlIiwgbGluZXR5cGUgPSAibG9uZ2Rhc2giLCBhbHBoYSA9IDAuNSkgKyAKICAjIGdlb21fc3RlcChkYXRhID0gbW91dGgsIGFlcyh4ID0gc2VjLCB5ID0geSksIGNvbG9yID0gImJsYWNrIiwgbGluZXR5cGUgPSAibG9uZ2Rhc2giLCBhbHBoYSA9IDAuNSkgKyAKICAjIGFubm90YXRlKCJ0ZXh0IiwgbGFiZWwgPSAiUmlnaHQgSGFuZCIsIHggPSAzLCB5ID0gMTAwMCwgY29sb3IgPSAicmVkIiwgYWxwaGEgPSAwLjUpICsKICAjIGFubm90YXRlKCJ0ZXh0IiwgbGFiZWwgPSAiTGVmdCBIYW5kIiwgeCA9IDMsIHkgPSAxMTAwLCBjb2xvciA9ICJibHVlIiwgYWxwaGEgPSAwLjUpICsKICAjIGFubm90YXRlKCJ0ZXh0IiwgbGFiZWwgPSAiTW91dGgiLCB4ID0gMywgeSA9IDIwMCwgY29sb3IgPSAiYmxhY2siLCBhbHBoYSA9IDAuNSkgKwogIGdndGl0bGUoIlN0ZXBoYW5pZSIpICsKICB0aGVtZV9idygpICsKICB0aGVtZShwYW5lbC5ncmlkLm1pbm9yLnkgPSBlbGVtZW50X2JsYW5rKCkpCgpzdGVwaCAlPiUKICBnZ3Bsb3QoYWVzKHggPSBzZWNzLCB5ID0geSkpICsgCiAgc2NhbGVfeV9yZXZlcnNlKGxpbWl0cyA9IGMoMTIwMCwwKSwgZXhwYW5kID0gYygwLDApKSArIAogIGdlb21fbGluZShhbHBoYSA9IDEsIGNvbG9yID0gInB1cnBsZSIpICsgCiAgIyBhbm5vdGF0ZSgicmVjdCIsIHhtaW4gPSA3LjkyLCB4bWF4ID0gOC45MiwgeW1pbiA9IDAsIHltYXggPSAxMjAwLAogICMgYWxwaGEgPSAuMiwgZmlsbCA9ICJyZWQiKSArCiAgIyBhbm5vdGF0ZSgicmVjdCIsIHhtaW4gPSAxMC42LCB4bWF4ID0gMTEuNTIsIHltaW4gPSAwLCB5bWF4ID0gMTIwMCwKICAjIGFscGhhID0gLjIsIGZpbGwgPSAicmVkIikgKwogICMgYW5ub3RhdGUoInJlY3QiLCB4bWluID0gMTQuMDgsIHhtYXggPSAxNS4yLCB5bWluID0gMCwgeW1heCA9IDEyMDAsCiAgIyBhbHBoYSA9IC4yLCBmaWxsID0gInJlZCIpICsKIyAgZ2VvbV9zdGVwKGRhdGEgPSByaGFuZCwgYWVzKHggPSBzZWMsIHkgPSB5KSwgY29sb3IgPSAicmVkIiwgbGluZXR5cGUgPSAibG9uZ2Rhc2giLCBhbHBoYSA9IDAuNSkgKyAKIyAgZ2VvbV9zdGVwKGRhdGEgPSBsaGFuZCwgYWVzKHggPSBzZWMsIHkgPSB5KSwgY29sb3IgPSAiYmx1ZSIsIGxpbmV0eXBlID0gImxvbmdkYXNoIiwgYWxwaGEgPSAwLjUpICsgCiAgZ2VvbV9zdGVwKGRhdGEgPSBtb3V0aCwgYWVzKHggPSBzZWMsIHkgPSB5KSwgY29sb3IgPSAiYmxhY2siLCBsaW5ldHlwZSA9ICJsb25nZGFzaCIsIGFscGhhID0gMC41KSArIAojIGFubm90YXRlKCJ0ZXh0IiwgbGFiZWwgPSAiUmlnaHQgSGFuZCIsIHggPSAzLCB5ID0gMTAwMCwgY29sb3IgPSAicmVkIiwgYWxwaGEgPSAwLjUpICsKIyAgYW5ub3RhdGUoInRleHQiLCBsYWJlbCA9ICJMZWZ0IEhhbmQiLCB4ID0gMywgeSA9IDExMDAsIGNvbG9yID0gImJsdWUiLCBhbHBoYSA9IDAuNSkgKwogIGFubm90YXRlKCJ0ZXh0IiwgbGFiZWwgPSAiTW91dGgiLCB4ID0gMywgeSA9IDI1MCwgY29sb3IgPSAiYmxhY2siLCBhbHBoYSA9IDAuNSkgKwogIGdndGl0bGUoIlN0ZXBoYW5pZSIpICsKICB0aGVtZV9idygpICsKICB0aGVtZShwYW5lbC5ncmlkLm1pbm9yLnkgPSBlbGVtZW50X2JsYW5rKCkpCgpzdGVwaCAlPiUKICBnZ3Bsb3QoYWVzKHggPSBzZWNzLCB5ID0geSkpICsgCiAgc2NhbGVfeV9yZXZlcnNlKGxpbWl0cyA9IGMoMTIwMCwwKSwgZXhwYW5kID0gYygwLDApKSArIAogIGdlb21fbGluZShhbHBoYSA9IDEsIGNvbG9yID0gInB1cnBsZSIpICsgCiAgIyBhbm5vdGF0ZSgicmVjdCIsIHhtaW4gPSA3LjkyLCB4bWF4ID0gOC45MiwgeW1pbiA9IDAsIHltYXggPSAxMjAwLAogICMgYWxwaGEgPSAuMiwgZmlsbCA9ICJyZWQiKSArCiAgIyBhbm5vdGF0ZSgicmVjdCIsIHhtaW4gPSAxMC42LCB4bWF4ID0gMTEuNTIsIHltaW4gPSAwLCB5bWF4ID0gMTIwMCwKICAjIGFscGhhID0gLjIsIGZpbGwgPSAicmVkIikgKwogICMgYW5ub3RhdGUoInJlY3QiLCB4bWluID0gMTQuMDgsIHhtYXggPSAxNS4yLCB5bWluID0gMCwgeW1heCA9IDEyMDAsCiAgIyBhbHBoYSA9IC4yLCBmaWxsID0gInJlZCIpICsKICBnZW9tX3N0ZXAoZGF0YSA9IHJoYW5kLCBhZXMoeCA9IHNlYywgeSA9IHkpLCBjb2xvciA9ICJyZWQiLCBsaW5ldHlwZSA9ICJsb25nZGFzaCIsIGFscGhhID0gMC41KSArIAojICBnZW9tX3N0ZXAoZGF0YSA9IGxoYW5kLCBhZXMoeCA9IHNlYywgeSA9IHkpLCBjb2xvciA9ICJibHVlIiwgbGluZXR5cGUgPSAibG9uZ2Rhc2giLCBhbHBoYSA9IDAuNSkgKyAKICBnZW9tX3N0ZXAoZGF0YSA9IG1vdXRoLCBhZXMoeCA9IHNlYywgeSA9IHkpLCBjb2xvciA9ICJibGFjayIsIGxpbmV0eXBlID0gImxvbmdkYXNoIiwgYWxwaGEgPSAwLjUpICsgCiAgYW5ub3RhdGUoInRleHQiLCBsYWJlbCA9ICJSaWdodCBIYW5kIiwgeCA9IDMsIHkgPSAxMDAwLCBjb2xvciA9ICJyZWQiLCBhbHBoYSA9IDAuNSkgKwojICBhbm5vdGF0ZSgidGV4dCIsIGxhYmVsID0gIkxlZnQgSGFuZCIsIHggPSAzLCB5ID0gMTEwMCwgY29sb3IgPSAiYmx1ZSIsIGFscGhhID0gMC41KSArCiAgYW5ub3RhdGUoInRleHQiLCBsYWJlbCA9ICJNb3V0aCIsIHggPSAzLCB5ID0gMjUwLCBjb2xvciA9ICJibGFjayIsIGFscGhhID0gMC41KSArCiAgZ2d0aXRsZSgiU3RlcGhhbmllIikgKwogIHRoZW1lX2J3KCkgKwogIHRoZW1lKHBhbmVsLmdyaWQubWlub3IueSA9IGVsZW1lbnRfYmxhbmsoKSkKCnN0ZXBoICU+JQogIGdncGxvdChhZXMoeCA9IHNlY3MsIHkgPSB5KSkgKyAKICBzY2FsZV95X3JldmVyc2UobGltaXRzID0gYygxMjAwLDApLCBleHBhbmQgPSBjKDAsMCkpICsgCiAgZ2VvbV9saW5lKGFscGhhID0gMSwgY29sb3IgPSAicHVycGxlIikgKyAKICAjIGFubm90YXRlKCJyZWN0IiwgeG1pbiA9IDcuOTIsIHhtYXggPSA4LjkyLCB5bWluID0gMCwgeW1heCA9IDEyMDAsCiAgIyBhbHBoYSA9IC4yLCBmaWxsID0gInJlZCIpICsKICAjIGFubm90YXRlKCJyZWN0IiwgeG1pbiA9IDEwLjYsIHhtYXggPSAxMS41MiwgeW1pbiA9IDAsIHltYXggPSAxMjAwLAogICMgYWxwaGEgPSAuMiwgZmlsbCA9ICJyZWQiKSArCiAgIyBhbm5vdGF0ZSgicmVjdCIsIHhtaW4gPSAxNC4wOCwgeG1heCA9IDE1LjIsIHltaW4gPSAwLCB5bWF4ID0gMTIwMCwKICAjIGFscGhhID0gLjIsIGZpbGwgPSAicmVkIikgKwogIGdlb21fc3RlcChkYXRhID0gcmhhbmQsIGFlcyh4ID0gc2VjLCB5ID0geSksIGNvbG9yID0gInJlZCIsIGxpbmV0eXBlID0gImxvbmdkYXNoIiwgYWxwaGEgPSAwLjUpICsgCiAgZ2VvbV9zdGVwKGRhdGEgPSBsaGFuZCwgYWVzKHggPSBzZWMsIHkgPSB5KSwgY29sb3IgPSAiYmx1ZSIsIGxpbmV0eXBlID0gImxvbmdkYXNoIiwgYWxwaGEgPSAwLjUpICsgCiAgZ2VvbV9zdGVwKGRhdGEgPSBtb3V0aCwgYWVzKHggPSBzZWMsIHkgPSB5KSwgY29sb3IgPSAiYmxhY2siLCBsaW5ldHlwZSA9ICJsb25nZGFzaCIsIGFscGhhID0gMC41KSArIAogIGFubm90YXRlKCJ0ZXh0IiwgbGFiZWwgPSAiUmlnaHQgSGFuZCIsIHggPSAzLCB5ID0gMTAwMCwgY29sb3IgPSAicmVkIiwgYWxwaGEgPSAwLjUpICsKICBhbm5vdGF0ZSgidGV4dCIsIGxhYmVsID0gIkxlZnQgSGFuZCIsIHggPSAzLCB5ID0gMTEwMCwgY29sb3IgPSAiYmx1ZSIsIGFscGhhID0gMC41KSArCiAgYW5ub3RhdGUoInRleHQiLCBsYWJlbCA9ICJNb3V0aCIsIHggPSAzLCB5ID0gMjUwLCBjb2xvciA9ICJibGFjayIsIGFscGhhID0gMC41KSArCiAgZ2d0aXRsZSgiU3RlcGhhbmllIikgKwogIHRoZW1lX2J3KCkgKwogIHRoZW1lKHBhbmVsLmdyaWQubWlub3IueSA9IGVsZW1lbnRfYmxhbmsoKSkKYGBgCgpOb3cgbGV0J3Mgd29yayBvbiBjb3JyZWxhdGlvbnMuIEZpcnN0LCBvdXIgQU9JIHZlY3RvcnMgYXJlIG5vdCB0aGUgc2FtZSBzaXplIGFzIG91ciBleWUgZ2F6ZSB2ZWN0b3JzLCBhbmQgdGhlIHgveSBwb3NpdGlvbiBpcyBpcnJlZ3VsYXJseSBzcGFjZWQgYWNyb3NzIHRpbWUgKGlycmVndWxhcmx5IHNwYWNlZCBrZXkgZnJhbWVzKS4gCmBgYHtyfQojIFRoZSBmb2xsb3dpbmcgY29kZSB3aWxsICJleHBhbmQiIHRoZSByaGFuZCBkYXRhIHZlY3RvcnMgdG8gZml0IHRoZSBsZW5ndGggb2YgU3RlcGhhbmllJ3MgZGF0YSB2ZWN0b3JzLgp0aW1lX2luZGV4IDwtIHN0ZXBoJHNlY3MKY2xvc2VzdCA8LSBmdW5jdGlvbih4KXsKICB3aGljaC5taW4oYWJzKHRpbWVfaW5kZXgteCkpCn0KCmluZGV4X2xvYyA8LSBtYXBfaW50KHJoYW5kJHNlYywgY2xvc2VzdCkKCnJoYW5kIDwtIGNiaW5kKHJoYW5kLCB0aW1lX2luZGV4W2luZGV4X2xvY10pICU+JQogIHNlbGVjdCgtc2VjKSAlPiUKICByZW5hbWUoc2VjID0gInRpbWVfaW5kZXhbaW5kZXhfbG9jXSIpICU+JQogIHNlbGVjdChzZWMsIHgsIHkpCgpyaGFuZF9mdWxsIDwtIHNlbGVjdChzdGVwaCwgc2VjcykgJT4lCiAgcmVuYW1lKHNlYyA9IHNlY3MpICU+JQogIGxlZnRfam9pbihyaGFuZCkgJT4lCiAgZmlsbCh4KSAlPiUKICBmaWxsKHkpICU+JQogIHNsaWNlKDE6KG5yb3coLiktMSkpCgpyaGFuZF9mdWxsIDwtIHJoYW5kX2Z1bGwgJT4lCiAgZmlsdGVyKHNlYyA8IHJoYW5kJHNlY1sxNzJdKSAlPiUKICBmaWx0ZXIoc2VjID49IHJoYW5kJHNlY1syXSkKCnN0ZXBoIDwtIHN0ZXBoICU+JQogIGZpbHRlcihzZWNzIDwgcmhhbmQkc2VjWzE3Ml0pICU+JQogIGZpbHRlcihzZWNzID49IHJoYW5kJHNlY1syXSkKCmEgPC0gcmhhbmRfZnVsbCR5CmEgPC0gYVsxOmxlbmd0aChhKS0xXSAjIFNob3J0ZW4gaXQgYnkgb25lIGVsZW1lbnQKYiA8LSBzdGVwaCR5CgojIFRoZW4gcnVuIGNvcnJlbGF0aW9ucwpjb3IoYSxiLCB1c2UgPSAiY29tcGxldGUub2JzIikgIyBiYXNpYyBjb3JyZWxhdGlvbgp0aGF0IDwtIGNjZihhLGIsIGxhZy5tYXggPSA0MDAsIHR5cGUgPSAiY29ycmVsYXRpb24iLCBuYS5hY3Rpb24gPSBuYS5wYXNzLCBwbG90ID0gVCkgIyBhdXRvLWNvcnJlbGF0aW9uCmBgYAoKCkxldCdzIHNlcGFyYXRlIG91dCBpbmRpdmlkdWFsIHNpZ25lcnMuIAoKYGBge3J9Cm1ha2Vfc2lnbmVyX3Bsb3RzIDwtIGZ1bmN0aW9uKGdyb3VwbmFtZSwgbGluZV9jb2xvcikgewogIGRhdGEgJT4lCiAgZmlsdGVyKG1haW5ncm91cCA9PSBncm91cG5hbWUpICU+JQogIGdncGxvdChhZXMoeCA9IHNlY3MsIHkgPSB5KSkgKyAKICBzY2FsZV95X3JldmVyc2UoKSArIAogIGdlb21fbGluZShhbHBoYSA9IDEsIGNvbG9yID0gbGluZV9jb2xvcikgKyAKICBhbm5vdGF0ZSgicmVjdCIsIHhtaW4gPSA3LjkyLCB4bWF4ID0gOC45MiwgeW1pbiA9IDAsIHltYXggPSA5MDAsCiAgYWxwaGEgPSAuMiwgZmlsbCA9ICJyZWQiKSArCiAgYW5ub3RhdGUoInJlY3QiLCB4bWluID0gMTAuNiwgeG1heCA9IDExLjUyLCB5bWluID0gMCwgeW1heCA9IDkwMCwKICBhbHBoYSA9IC4yLCBmaWxsID0gInJlZCIpICsKICBhbm5vdGF0ZSgicmVjdCIsIHhtaW4gPSAxNC4wOCwgeG1heCA9IDE1LjIsIHltaW4gPSAwLCB5bWF4ID0gOTAwLAogIGFscGhhID0gLjIsIGZpbGwgPSAicmVkIikgKwogIGdlb21fc3RlcChkYXRhID0gcmhhbmQsIGFlcyh4ID0gc2VjLCB5ID0geSksIGNvbG9yID0gInJlZCIsIGxpbmV0eXBlID0gImxvbmdkYXNoIiwgYWxwaGEgPSAwLjUpICsgCiAgZ2VvbV9zdGVwKGRhdGEgPSBsaGFuZCwgYWVzKHggPSBzZWMsIHkgPSB5KSwgY29sb3IgPSAiYmx1ZSIsIGxpbmV0eXBlID0gImxvbmdkYXNoIiwgYWxwaGEgPSAwLjUpICsgCiAgZ2VvbV9zdGVwKGRhdGEgPSBtb3V0aCwgYWVzKHggPSBzZWMsIHkgPSB5KSwgY29sb3IgPSAiYmxhY2siLCBsaW5ldHlwZSA9ICJsb25nZGFzaCIsIGFscGhhID0gMC41KSArIAogIGFubm90YXRlKCJ0ZXh0IiwgbGFiZWwgPSAiUmlnaHQgSGFuZCIsIHggPSAzLCB5ID0gMTAwMCwgY29sb3IgPSAicmVkIiwgYWxwaGEgPSAwLjUpICsKICBhbm5vdGF0ZSgidGV4dCIsIGxhYmVsID0gIkxlZnQgSGFuZCIsIHggPSAzLCB5ID0gMTEwMCwgY29sb3IgPSAiYmx1ZSIsIGFscGhhID0gMC41KSArCiAgYW5ub3RhdGUoInRleHQiLCBsYWJlbCA9ICJNb3V0aCIsIHggPSAzLCB5ID0gMjAwLCBjb2xvciA9ICJibGFjayIsIGFscGhhID0gMC41KSArCiAgZmFjZXRfZ3JpZChuYW1lIH4gLikgKwogIGdndGl0bGUoZ3JvdXBuYW1lKSArCiAgdGhlbWVfYncoKQp9CgptYWtlX3NpZ25lcl9wbG90cygiRGVhZkVhcmx5IiwgInJlZCIpCm1ha2Vfc2lnbmVyX3Bsb3RzKCJEZWFmTGF0ZSIsICJkYXJrIGdyZWVuIikKbWFrZV9zaWduZXJfcGxvdHMoIkhlYXJpbmdMYXRlIiwgImJsdWUiKQptYWtlX3NpZ25lcl9wbG90cygiSGVhcmluZ05vdmljZSIsICJwdXJwbGUiKQpgYGAKCk9rYXkgc28gd2l0aCBFYXJseSBBU0wgb2J2aW91c2x5IHZlcnkgc3RlYWR5IGdhemUuIE5vdmljZUFTTCBoYXMgbG90IG9mIGRvd25zaGlmdHMuIFNvbWUgYWxpZ24gd2l0aCBzcGF0aWFsIHJlZmVyZW5jaW5nLCBzb21lIGRvIG5vdC4gV2UgbmVlZCBtb3JlIG9mIHRoZW0gKGxldCdzIGxvb2sgYXQgb3RoZXIgc3RvcmllcyB3IGJldHRlciBkYXRhKS4gCgoKIyBNaWRhcyBGb3J3YXJkCgpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQojIEdldCBNaWRhcyBkYXRhCmRhdGEgPC0gcmVhZF9jc3YoIi4uL0FkdWx0IERhdGEvcmF3ZGF0YS9taWRhc2Z3LmNzdiIpICU+JQogIGNsZWFuX25hbWVzKCkgJT4lCiAgcmVuYW1lKHkgPSBnYXplX3BvaW50X3lfbWNfc3B4LAogICAgICAgICBsYW5ndWFnZSA9IGxhbmd1YWdlX3ZhbHVlLAogICAgICAgICBuYW1lID0gcGFydGljaXBhbnRfbmFtZSwKICAgICAgICAgZ3JvdXAgPSBncm91cF92YWx1ZSkKCiMgUHVsbCBjbGVhbiBuYW1lcyBhbmQgam9pbiB0byBkYXRhCmNsZWFubmFtZXMgPC0gcmVhZF9jc3YoInBhcnRuYW1lcy5jc3YiKSAlPiUKICBkaXN0aW5jdCgpICU+JQogIHJlbmFtZShuYW1lID0gcGFydGljaXBhbnQpCgpkYXRhIDwtIGRhdGEgJT4lIGxlZnRfam9pbihjbGVhbm5hbWVzLCBieSA9ICJuYW1lIikgJT4lCiAgc2VsZWN0KC1uYW1lKSAlPiUKICByZW5hbWUobmFtZSA9IG5ld19wYXJ0aWNpcGFudCkgJT4lCiAgZmlsdGVyKCFpcy5uYShuYW1lKSkKCiMgUHVsbCBmaW5hbCBncm91cCBhc3NpZ25tZW50cyBhbmQgam9pbiB0byBkYXRhCmNsZWFuZ3JvdXBzIDwtIHJlYWRfY3N2KCJmaW5hbGRhdGFzZXQuY3N2IikgJT4lCiAgc2VsZWN0KHBhcnRpY2lwYW50LCBtYWluZ3JvdXApICU+JQogIHJlbmFtZShuYW1lID0gcGFydGljaXBhbnQpICU+JQogIGRpc3RpbmN0KCkKCmRhdGEgPC0gZGF0YSAlPiUgbGVmdF9qb2luKGNsZWFuZ3JvdXBzLCBieSA9ICJuYW1lIikgJT4lCiAgc2VsZWN0KC1ncm91cCkKCiMgTGV0J3MgZmluZCBvdXQgd2hvIHdhcyBOT1QgaW5jbHVkZWQgaW4gVGhyZWUgQmVhcnMKZXhjbHVkZWQgPC0gcmVhZF9jc3YoImZpbmFsZGF0YXNldC5jc3YiKSAlPiUKICBzZWxlY3QocGFydGljaXBhbnQsIG1haW5ncm91cCwgc3RvcnksIGRpcmVjdGlvbiwgZXllX2V4Y2x1ZGUpICU+JQogIGZpbHRlcihzdG9yeSA9PSAiS2luZ01pZGFzIiAmIGRpcmVjdGlvbiA9PSAiZm9yd2FyZCIpICU+JQogIHJlbmFtZShuYW1lID0gcGFydGljaXBhbnQpICU+JQogIHNlbGVjdChuYW1lLCBleWVfZXhjbHVkZSkKCmRhdGEgPC0gZGF0YSAlPiUgbGVmdF9qb2luKGV4Y2x1ZGVkLCBieSA9ICJuYW1lIikgJT4lCiAgZmlsdGVyKCFleWVfZXhjbHVkZSkgJT4lCiAgZmlsdGVyKCFpcy5uYShleWVfZXhjbHVkZSkpCgpkYXRhICU+JSBzZWxlY3QobmFtZSwgbWFpbmdyb3VwKSAlPiUgZGlzdGluY3QoKQpgYGAKCk5vdyBsZXQncyBncmFwaCEhIAoKSG0uIE9uZSBwZXJzb24gc2VlbXMgd3JvbmcuIApgYGB7cn0KZGF0YSAlPiUKICBnZ3Bsb3QoYWVzKHggPSBnYXplX3BvaW50X2luZGV4LCB5ID0geSwgY29sb3IgPSBtYWluZ3JvdXAsIGdyb3VwID0gbmFtZSkpICsgZ2VvbV9saW5lKCkgKyBzY2FsZV95X3JldmVyc2UoKQpgYGAKT2theSBpdCdzIEplc3NlJ3MgZGF0YSB0aGF0IHNlZW1zIG9mZi4gV2UnbGwgcmVtb3ZlIGhpbSBmb3Igbm93IGFuZCBjb21lIGJhY2sgdG8gaXQsIGZpZ3VyZSBvdXQgd2h5LiAKYGBge3J9CmRhdGEgJT4lIGZpbHRlcihnYXplX3BvaW50X2luZGV4ID4gMzAwMDApICU+JSBzZWxlY3QobmFtZSkgJT4lIGRpc3RpbmN0KCkgJT4lIGhlYWQoKQpgYGAKCmBgYHtyfQpkYXRhIDwtIGRhdGEgJT4lCiAgZmlsdGVyKG5hbWUgIT0gIkplc3NlIikKCmRhdGEgJT4lCiAgZ2dwbG90KGFlcyh4ID0gZ2F6ZV9wb2ludF9pbmRleCwgeSA9IHksIGNvbG9yID0gbWFpbmdyb3VwLCBncm91cCA9IG5hbWUpKSArIGdlb21fbGluZSgpICsgCiAgc2NhbGVfeV9yZXZlcnNlKCkgKwogIHNjYWxlX3hfY29udGludW91cyhsaW1pdHMgPSBjKDAsNDUwMCkpCmBgYAoKTmV4dCBsZXQncyBwbG90IHRoZSBtb21lbnRzIHdoZXJlIHNwYXRpYWwgcmVmZXJlbmNpbmcgaGFwcGVucy4gVGhvc2UgYXJlIGZyYW1lcwoKMS4gMjQ4IHRvIDQyNwoxLiA0NjAgdG8gNTA4CjEuIDUxMiB0byA1NjAKCkxpa2UgYmVmb3JlLCB3ZSdsbCBjb252ZXJ0IGdhemVwb2ludGluZGV4IHRvIHNlY29uZHMgKGJ5IGRpdmlkaW5nIDEyMCkgYW5kIGFsbCBmcmFtZXMgdG8gc2Vjb25kcyAoYnkgZGl2aWRpbmcgMjUpLiAKCjEuIDkuOTJzIHRvIDE3LjA4cwoxLiAxOC40cyB0byAyMC4zMnMKMS4gMjAuNDhzIHRvIDIyLjRzIAoKYGBge3J9CmRhdGEgPC0gZGF0YSAlPiUKICByb3d3aXNlKCkgJT4lCiAgbXV0YXRlKHNlY3MgPSBnYXplX3BvaW50X2luZGV4LzEyMCkKCmRhdGEgJT4lCiAgZ2dwbG90KGFlcyh4ID0gc2VjcywgeSA9IHksIGNvbG9yID0gbWFpbmdyb3VwLCBncm91cCA9IG5hbWUpKSArIAogIHNjYWxlX3lfcmV2ZXJzZSgpICsgCiAgc2NhbGVfeF9jb250aW51b3VzKGxpbWl0cyA9IGMoMCwgMzcuNSkpICsKICBnZW9tX2xpbmUoKSArIAogIGFubm90YXRlKCJyZWN0IiwgeG1pbiA9IDkuOTIsIHhtYXggPSAxNy4wOCwgeW1pbiA9IDAsIHltYXggPSA5MDAsCiAgYWxwaGEgPSAuMiwgZmlsbCA9ICJyZWQiKSArCiAgYW5ub3RhdGUoInJlY3QiLCB4bWluID0gMTguNCwgeG1heCA9IDIwLjMyLCB5bWluID0gMCwgeW1heCA9IDkwMCwKICBhbHBoYSA9IC4yLCBmaWxsID0gInJlZCIpICsKICBhbm5vdGF0ZSgicmVjdCIsIHhtaW4gPSAyMC40OCwgeG1heCA9IDIyLjQsIHltaW4gPSAwLCB5bWF4ID0gOTAwLAogIGFscGhhID0gLjIsIGZpbGwgPSAicmVkIikKYGBgCgpNYXliZSBlYXNpZXIgaWYgd2Ugc2VwYXJhdGUgZ3JvdXBzIG9mIHNpZ25lcnMuIAoKYGBge3J9CmRhdGEgJT4lCiAgZ2dwbG90KGFlcyh4ID0gc2VjcywgeSA9IHksIGNvbG9yID0gbWFpbmdyb3VwLCBncm91cCA9IG5hbWUpKSArIAogIHNjYWxlX3lfcmV2ZXJzZSgpICsgCiAgc2NhbGVfeF9jb250aW51b3VzKGxpbWl0cyA9IGMoMCwgMzcuNSkpICsKICBnZW9tX2xpbmUoYWxwaGEgPSAwLjUpICsgCiAgYW5ub3RhdGUoInJlY3QiLCB4bWluID0gOS45MiwgeG1heCA9IDE3LjA4LCB5bWluID0gMCwgeW1heCA9IDkwMCwKICBhbHBoYSA9IC4yLCBmaWxsID0gInJlZCIpICsKICBhbm5vdGF0ZSgicmVjdCIsIHhtaW4gPSAxOC40LCB4bWF4ID0gMjAuMzIsIHltaW4gPSAwLCB5bWF4ID0gOTAwLAogIGFscGhhID0gLjIsIGZpbGwgPSAicmVkIikgKwogIGFubm90YXRlKCJyZWN0IiwgeG1pbiA9IDIwLjQ4LCB4bWF4ID0gMjIuNCwgeW1pbiA9IDAsIHltYXggPSA5MDAsCiAgYWxwaGEgPSAuMiwgZmlsbCA9ICJyZWQiKSArCiAgZmFjZXRfZ3JpZChtYWluZ3JvdXAgfiAuKQpgYGAKCkluZGl2aWR1YWwgc2lnbmVycy4gCgpgYGB7cn0KZGF0YSAlPiUKICBmaWx0ZXIobWFpbmdyb3VwID09ICJEZWFmRWFybHkiKSAlPiUKICBnZ3Bsb3QoYWVzKHggPSBzZWNzLCB5ID0geSwgZ3JvdXAgPSBuYW1lKSkgKyAKICBzY2FsZV94X2NvbnRpbnVvdXMobGltaXRzID0gYygwLCAzNy41KSkgKwogIHNjYWxlX3lfcmV2ZXJzZSgpICsgCiAgZ2VvbV9saW5lKGFscGhhID0gMSwgY29sb3IgPSAicmVkIikgKyAKICBhbm5vdGF0ZSgicmVjdCIsIHhtaW4gPSA5LjkyLCB4bWF4ID0gMTcuMDgsIHltaW4gPSAwLCB5bWF4ID0gOTAwLAogIGFscGhhID0gLjIsIGZpbGwgPSAicmVkIikgKwogIGFubm90YXRlKCJyZWN0IiwgeG1pbiA9IDE4LjQsIHhtYXggPSAyMC4zMiwgeW1pbiA9IDAsIHltYXggPSA5MDAsCiAgYWxwaGEgPSAuMiwgZmlsbCA9ICJyZWQiKSArCiAgYW5ub3RhdGUoInJlY3QiLCB4bWluID0gMjAuNDgsIHhtYXggPSAyMi40LCB5bWluID0gMCwgeW1heCA9IDkwMCwKICBhbHBoYSA9IC4yLCBmaWxsID0gInJlZCIpICsKICBmYWNldF9ncmlkKG5hbWUgfiAuKSArCiAgZ2d0aXRsZSgiRGVhZkVhcmx5IikKCmRhdGEgJT4lCiAgZmlsdGVyKG1haW5ncm91cCA9PSAiRGVhZkxhdGUiKSAlPiUKICBnZ3Bsb3QoYWVzKHggPSBzZWNzLCB5ID0geSwgZ3JvdXAgPSBuYW1lKSkgKyAKICBzY2FsZV95X3JldmVyc2UoKSArIAogIHNjYWxlX3hfY29udGludW91cyhsaW1pdHMgPSBjKDAsIDM3LjUpKSArCiAgZ2VvbV9saW5lKGFscGhhID0gMSwgY29sb3IgPSAiZGFyayBncmVlbiIpICsgCiAgYW5ub3RhdGUoInJlY3QiLCB4bWluID0gOS45MiwgeG1heCA9IDE3LjA4LCB5bWluID0gMCwgeW1heCA9IDkwMCwKICBhbHBoYSA9IC4yLCBmaWxsID0gInJlZCIpICsKICBhbm5vdGF0ZSgicmVjdCIsIHhtaW4gPSAxOC40LCB4bWF4ID0gMjAuMzIsIHltaW4gPSAwLCB5bWF4ID0gOTAwLAogIGFscGhhID0gLjIsIGZpbGwgPSAicmVkIikgKwogIGFubm90YXRlKCJyZWN0IiwgeG1pbiA9IDIwLjQ4LCB4bWF4ID0gMjIuNCwgeW1pbiA9IDAsIHltYXggPSA5MDAsCiAgYWxwaGEgPSAuMiwgZmlsbCA9ICJyZWQiKSArCiAgZmFjZXRfZ3JpZChuYW1lIH4gLikgKwogIGdndGl0bGUoIkRlYWZMYXRlIikKCmRhdGEgJT4lCiAgZmlsdGVyKG1haW5ncm91cCA9PSAiSGVhcmluZ0xhdGUiKSAlPiUKICBnZ3Bsb3QoYWVzKHggPSBzZWNzLCB5ID0geSwgZ3JvdXAgPSBuYW1lKSkgKyAKICBzY2FsZV95X3JldmVyc2UoKSArIAogIHNjYWxlX3hfY29udGludW91cyhsaW1pdHMgPSBjKDAsIDM3LjUpKSArCiAgZ2VvbV9saW5lKGFscGhhID0gMSwgY29sb3IgPSAiYmx1ZSIpICsgCiAgYW5ub3RhdGUoInJlY3QiLCB4bWluID0gOS45MiwgeG1heCA9IDE3LjA4LCB5bWluID0gMCwgeW1heCA9IDkwMCwKICBhbHBoYSA9IC4yLCBmaWxsID0gInJlZCIpICsKICBhbm5vdGF0ZSgicmVjdCIsIHhtaW4gPSAxOC40LCB4bWF4ID0gMjAuMzIsIHltaW4gPSAwLCB5bWF4ID0gOTAwLAogIGFscGhhID0gLjIsIGZpbGwgPSAicmVkIikgKwogIGFubm90YXRlKCJyZWN0IiwgeG1pbiA9IDIwLjQ4LCB4bWF4ID0gMjIuNCwgeW1pbiA9IDAsIHltYXggPSA5MDAsCiAgYWxwaGEgPSAuMiwgZmlsbCA9ICJyZWQiKSArCiAgZmFjZXRfZ3JpZChuYW1lIH4gLikgKwogIGdndGl0bGUoIkhlYXJpbmdMYXRlIikKCmRhdGEgJT4lCiAgZmlsdGVyKG1haW5ncm91cCA9PSAiSGVhcmluZ05vdmljZSIpICU+JQogIGdncGxvdChhZXMoeCA9IHNlY3MsIHkgPSB5LCBncm91cCA9IG5hbWUpKSArIAogIHNjYWxlX3lfcmV2ZXJzZSgpICsgCiAgc2NhbGVfeF9jb250aW51b3VzKGxpbWl0cyA9IGMoMCwgMzcuNSkpICsKICBnZW9tX2xpbmUoYWxwaGEgPSAxLCBjb2xvciA9ICJwdXJwbGUiKSArIAogIGFubm90YXRlKCJyZWN0IiwgeG1pbiA9IDkuOTIsIHhtYXggPSAxNy4wOCwgeW1pbiA9IDAsIHltYXggPSA5MDAsCiAgYWxwaGEgPSAuMiwgZmlsbCA9ICJyZWQiKSArCiAgYW5ub3RhdGUoInJlY3QiLCB4bWluID0gMTguNCwgeG1heCA9IDIwLjMyLCB5bWluID0gMCwgeW1heCA9IDkwMCwKICBhbHBoYSA9IC4yLCBmaWxsID0gInJlZCIpICsKICBhbm5vdGF0ZSgicmVjdCIsIHhtaW4gPSAyMC40OCwgeG1heCA9IDIyLjQsIHltaW4gPSAwLCB5bWF4ID0gOTAwLAogIGFscGhhID0gLjIsIGZpbGwgPSAicmVkIikgKwogIGZhY2V0X2dyaWQobmFtZSB+IC4pICsKICBnZ3RpdGxlKCJIZWFyaW5nTm92aWNlIikKYGBg